This is a race bug.
The expected exception is a NullpointerException.
More details about this bug are at
JDK-7132378 JIRA page.
java.util.concurrent.FutureTask$Sync
t1 t2 V innerGet() throws InterruptedException, ExecutionException {
2 acquireSharedInterruptibly(0);
if (getState() == CANCELLED)
throw new CancellationException();
if (exception != null)
throw new ExecutionException(exception);
3 return result;
}
void innerSet(V v) {
for (;;) {
int s = getState();
if (s == RAN)
return;
if (s == CANCELLED) {
// aggressively release to set runner to null,
// in case we are racing with a cancel request
// that will try to interrupt runner
releaseShared(0);
return;
}
1 if (compareAndSetState(s, RAN)) {
4 result = v;
releaseShared(0);
done();
return;
}
}
}
Preconditions:
FuturnTask is not run.
a) thread 1 sets a value. It updates the task state to RAN at 1.
b) context switched, thread 2 acquires a continue signal at 2. The task
state has been set to RAN at step a). So here thread 2 does not need to
wait at 2.
c) thread 2 returns return that is null at 3.
d) context switched, thread 1 assigns a value to result. But unexpected
null value has been returned at step c).
This bug is reproduced under JDK 1.7.0.
It started at JDK 1.7.0, and has been fixed since JDK 1.7.0_40.
Execute the following scripts to run the test to reproduce the bug (assume the location of the jdk7 test project is jdk7_test_home).
Linux:
${jdk7_test_home}/scripts/7132378.sh [--javaloc path]
Windows:
%jdk7_test_home%\scripts\7132378.bat [--javaloc path]
| Option | Function |
| --javaloc | The location of JDK that is eligible to reproduce the bug,
if your java environment is not eligible. In this case, it's JDK 1.7.0. It should be the absolute path to the JDK's java starter and ended with "/". For example: ~/jdk/home/jdk1.7.0/bin/ |